home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1999 November / Macworld (1999-11).dmg / Updaters / WhiteCap 3.0.4 / WhiteCap Source.sit / WhiteCap Source / Common / General Tools / nodeClass.cpp < prev    next >
Text File  |  1999-07-13  |  19KB  |  934 lines

  1.  
  2. #include "nodeClass.h"
  3.  
  4. #include "CEgIStream.h"
  5. #include "CEgOStream.h"
  6.  
  7. #include <stdlib.h>
  8.  
  9.  
  10. #ifdef EG_DEBUG
  11. nodeClass*    nodeClass::sFirstDebug    = NULL;
  12. long        nodeClass::sCacheHitsA    = 0;
  13. long        nodeClass::sCacheHitsB    = 0;
  14. long        nodeClass::sCacheHitsC    = 0;
  15. long        nodeClass::sCacheTrysA    = 0;
  16. long        nodeClass::sCacheTrysB    = 0;
  17. long        nodeClass::sCacheTrysC    = 0;
  18. #pragma debug mode on
  19. #endif
  20.  
  21.  
  22. long            nodeClass::sClassIDs[ 30 ];
  23. CreatorFuncT    nodeClass::sCreatorFunc[ 30 ];
  24. int                nodeClass::sNumRegistered = 0;
  25.  
  26.     
  27. nodeClass::nodeClass() {
  28.  
  29.     initSelf();
  30. }
  31.  
  32.  
  33.  
  34.  
  35. nodeClass::nodeClass( nodeClass* inParentPtr ) {
  36.  
  37.     initSelf();
  38.     if ( inParentPtr )
  39.         inParentPtr -> addToTail( this );
  40. }
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49. nodeClass::~nodeClass() {
  50.     deleteContents();                                            // Dispose of contained nodes
  51.     detach();                                                    // Remove the node from the chain
  52.  
  53.     #ifdef EG_DEBUG    
  54.     nodeClass*    prevPtr = NULL;
  55.     nodeClass*    nodePtr = sFirstDebug;
  56.     
  57.     while ( nodePtr != this ) {
  58.         prevPtr = nodePtr;
  59.         nodePtr = nodePtr -> mNextDebug;
  60.     }
  61.         
  62.     if ( prevPtr )
  63.         prevPtr -> mNextDebug = mNextDebug;
  64.     else
  65.         sFirstDebug = mNextDebug;
  66.     #endif
  67. }
  68.  
  69.  
  70. #ifdef EG_DEBUG    
  71. void nodeClass::DebugBreak() {
  72.     int i = 0;
  73.     nodeClass*    nodePtr = sFirstDebug;
  74.     
  75.     while ( nodePtr ) {
  76.         i++;        // Break here!
  77.         nodePtr = nodePtr -> mNextDebug;
  78.     }
  79.  
  80.     i = i + 0;
  81. }
  82. #endif
  83.  
  84.  
  85.  
  86.  
  87. nodeClass* nodeClass::CreateNode( long inClassID, nodeClass* inParent ) {
  88.     int         i;
  89.     
  90.     for ( i = 0; i < sNumRegistered; i++ ) {
  91.         if ( sClassIDs[ i ] == inClassID )
  92.             return sCreatorFunc[ i ]( inParent );
  93.     }
  94.     
  95.     return NULL;
  96. }
  97.  
  98.             
  99.             
  100. void nodeClass::RegisterNodeClass( long inID, CreatorFuncT inCreatorFunc ) {
  101.     sClassIDs[ sNumRegistered ]        = inID;
  102.     sCreatorFunc[ sNumRegistered ]     = inCreatorFunc;
  103.     sNumRegistered++;
  104. }
  105.  
  106.  
  107.  
  108. void nodeClass::initSelf() {
  109.     mNext = NULL;
  110.     mPrev = NULL;
  111.     mParent = NULL;
  112.  
  113.     mTail = NULL;
  114.     mHead = NULL;
  115.     
  116.     mFlags = 0;
  117.     mDeepCount        = -1;
  118.     mShallowCount    = 0;
  119.     
  120.     mType = nodeClassT;
  121.  
  122.     #ifdef EG_DEBUG
  123.     mNextDebug = sFirstDebug;
  124.     sFirstDebug = this;
  125.     #endif
  126. }
  127.  
  128.  
  129.  
  130.  
  131. void nodeClass::SetTreeSelected( bool inSelected ) {
  132.     nodeClass*    nodePtr = mHead;
  133.     
  134.     SetSelected( inSelected );
  135.     
  136.     while ( nodePtr ) {
  137.         nodePtr -> SetTreeSelected( inSelected );
  138.         nodePtr = nodePtr -> GetNext();
  139.     }
  140. }
  141.  
  142.  
  143.  
  144.  
  145.  
  146.  
  147.  
  148. void nodeClass::DeleteSelected() {
  149.     nodeClass*    nodePtr = mHead;
  150.     nodeClass*    delPtr;
  151.     
  152.     while ( nodePtr ) {
  153.         if ( nodePtr -> IsSelected() ) {
  154.             nodePtr -> absorbAfter( nodePtr );
  155.             delPtr = nodePtr;
  156.             nodePtr = nodePtr -> GetNext();
  157.             delete delPtr; }
  158.         else {
  159.             nodePtr -> DeleteSelected();
  160.             nodePtr = nodePtr -> GetNext();
  161.         }
  162.     }
  163. }
  164.  
  165.  
  166.  
  167.  
  168.  
  169.  
  170. bool nodeClass::CheckInsertPt( long& ioNodeNum, long& ioDepth ) {
  171.     nodeClass*    insertPt;
  172.     long        min, max, n = deepCount();
  173.     
  174.     if ( ioNodeNum > n )
  175.         ioNodeNum = n;
  176.  
  177.     if ( ioDepth < 0 )
  178.         ioDepth = 0;
  179.                     
  180.     insertPt = findSubNode( ioNodeNum );
  181.     
  182.     if ( insertPt ) {
  183.         max = insertPt -> CountDepth( this );
  184.             
  185.         if ( ioDepth > max )
  186.             ioDepth = max;
  187.             
  188.         if ( insertPt -> shallowCount() > 0 )
  189.             min = max; 
  190.         else
  191.             min = max - insertPt -> CountOverhang( this ) - 1;
  192.             
  193.         if ( ioDepth < min )
  194.             ioDepth = min;
  195.     /*
  196.         the following moves the cursor around, moving it to valid insert positions like meterowerks'
  197.         project manager... it works great, but it's too advanced for our particular novice computer users. 
  198.             
  199.         for ( n = 0; n <= max - ioDepth - 1; n++ ) {
  200.             ioNodeNum = findSubNode( insertPt ) + insertPt -> deepCount();
  201.             insertPt = insertPt -> GetParent();
  202.         }*/ 
  203.         
  204.         }
  205.     else {
  206.         ioNodeNum = 0;
  207.         ioDepth = 0; 
  208.     }
  209.         
  210.     return true;
  211. }
  212.  
  213.  
  214.  
  215. void nodeClass::MoveSelected( long afterItemNum, long inDepth ) {
  216.     nodeClass*    nextPtr, *nodePtr;
  217.     nodeClass    moveList;
  218.     nodeClass*    insertPt = findSubNode( afterItemNum );
  219.     long         relDepth = 0;
  220.     
  221.     if ( insertPt ) {
  222.         if ( insertPt -> IsSelected() && insertPt -> PrevInChain( this ) == insertPt -> GetPrev() )
  223.             insertPt = insertPt -> GetPrev();                            // Allow special case
  224.             
  225.         if ( insertPt -> IsSelected() ) {                                // We can't insert the insert node!
  226.             while ( insertPt ? insertPt -> IsSelected() : false ) {        // Make sure insert pt is not selected 
  227.                 insertPt = insertPt -> PrevInChain( this );
  228.             }
  229.         }
  230.         
  231.         if ( insertPt ) {
  232.             relDepth = insertPt -> CountDepth( this ) - inDepth - 1;     // How many levels we must rise
  233.             
  234.             while ( relDepth > 0 && insertPt ) {                         // Adj the insert node based on <inDepth>
  235.                 insertPt = insertPt -> GetParent();
  236.                 relDepth--;
  237.             }
  238.         }
  239.     }
  240.     
  241.     if ( insertPt ) {
  242.         nodePtr = insertPt -> GetParent();
  243.         while ( nodePtr && nodePtr != this ) {                            // Prevent circular containment by deselecting
  244.             nodePtr -> Unselect();                                        // parents of the insertion node
  245.             nodePtr = nodePtr -> GetParent();
  246.         } }
  247.     else {                                                                // If no insert pt, we add to this' head.
  248.         insertPt = this;
  249.         relDepth = -1;                                                    // Signal to add to head
  250.     }
  251.     
  252.  
  253.     nodePtr = mHead;
  254.     while ( nodePtr ) {
  255.         if ( nodePtr -> IsSelected() ) {
  256.             nextPtr = nodePtr -> PrevInChain( this );                    // Save where we'll resume
  257.             moveList.addToTail( nodePtr );                                // Add the selected item (and its sub tree) to a temp list
  258.             if ( nextPtr )                                                // If we can resume where we left off...
  259.                 nodePtr = nextPtr;
  260.             else                                                         // If nodePtr was at the head of this 
  261.                 nodePtr = mHead;    }                                    // Start over again
  262.         else
  263.             nodePtr = nodePtr -> NextInChain( this );        
  264.     }
  265.         
  266.     nodePtr = moveList.GetTail();
  267.     while ( nodePtr ) {
  268.         if ( relDepth < 0 )
  269.             insertPt -> addToHead( nodePtr );
  270.         else
  271.             nodePtr -> insertAfter( insertPt );
  272.         VerifyNode( nodePtr );
  273.                     
  274.         nodePtr = moveList.GetTail();
  275.     }
  276. }
  277.  
  278.  
  279.  
  280.  
  281.  
  282.  
  283.  
  284.  
  285.  
  286. void nodeClass::VerifyNode( nodeClass* ) {
  287.     
  288.  
  289. }
  290.  
  291.  
  292.  
  293.  
  294. void nodeClass::absorbMarked( nodeClass* inSourceList ) {
  295.     nodeClass*    nodePtr = NULL;
  296.     nodeClass*    nextPtr;
  297.     
  298.     if ( inSourceList )
  299.         nodePtr = inSourceList -> GetHead();
  300.  
  301.     while ( nodePtr ) {
  302.         nextPtr = nodePtr -> GetNext();
  303.         if ( nodePtr -> IsSelected() ) 
  304.             addToTail( nodePtr );
  305.         else
  306.             absorbMarked( nodePtr );
  307.  
  308.         nodePtr = nextPtr;
  309.     }
  310.     
  311. }
  312.  
  313.  
  314.  
  315. bool nodeClass::HasTheParent( const nodeClass* inMaybeParent ) const {
  316.     nodeClass* parPtr = mParent;
  317.     
  318.     if ( inMaybeParent ) {
  319.         while ( parPtr ) {
  320.             if ( parPtr == inMaybeParent )
  321.                 return true;
  322.             else
  323.                 parPtr = parPtr -> GetParent();
  324.         }
  325.     }
  326.  
  327.     return false;
  328. }
  329.  
  330.         
  331.         
  332. void nodeClass::SetFlag( unsigned int inFlagNum, bool inVal ) {
  333.     unsigned short m;
  334.     
  335.     if ( inFlagNum >= 1 && inFlagNum <= 9 ) {
  336.         m = 0x1 << inFlagNum;
  337.         if ( inVal )
  338.             mFlags |= m;
  339.         else
  340.             mFlags &= ~m;
  341.     }
  342. }
  343.         
  344.  
  345.  
  346. bool nodeClass::GetFlag( unsigned int inFlagNum ) const {
  347.     unsigned short m;
  348.     
  349.     if ( inFlagNum >= 1 && inFlagNum <= 9 ) {
  350.         m = 0x1 << inFlagNum;
  351.         return mFlags & m; }
  352.     else
  353.         return false;
  354. }
  355.  
  356.  
  357.  
  358.  
  359. void nodeClass::UpdateCounts( int inShallowChange ) {
  360.     if ( inShallowChange != 0 )
  361.         mShallowCount += inShallowChange;                        // Update shallow count
  362.         
  363.     mDeepCount    = -1;                                            // Invalidate deep count
  364.         
  365.     if ( mParent )
  366.         mParent -> UpdateCounts( 0 );                            // Propigate the dirty info
  367. }
  368.  
  369.  
  370. void nodeClass::detach() {
  371.     if ( mParent ) {
  372.         mParent -> UpdateCounts( -1 );
  373.         
  374.         if ( mPrev )                                            // if a link proceeds...
  375.             mPrev -> mNext = mNext;                             // tell prev link where the new next link is
  376.         else                                                    // if this is the 1st item...
  377.             mParent -> mHead = mNext;                            // tell header where new 1st link is
  378.             
  379.         if ( mNext )                                            // if a link follows...
  380.             mNext -> mPrev = mPrev;                             // tell next link where the new prev link is
  381.         else                                                     // is this is the last item...
  382.             mParent -> mTail = mPrev;                            // tell header where new last link is
  383.     }
  384.     
  385.     mNext = NULL;                                                // if something still points here,
  386.     mPrev = NULL;                                                // the data remaining will be NULL/bad;
  387.     mParent = NULL;                                                // be safe
  388.  
  389. }
  390.  
  391.  
  392.  
  393.  
  394.  
  395. void nodeClass::insertAfter( nodeClass* inBefore ) {
  396.  
  397.     if ( inBefore && inBefore != this ) {
  398.         if ( inBefore -> GetNext() != this ) {
  399.             detach();                                                    // Detach this ob before we go attaching somewhere else
  400.             mParent = inBefore -> GetParent();                            // set this object's parent group ptr
  401.             
  402.             if ( mParent ) {
  403.                 mParent -> UpdateCounts( 1 );
  404.                 
  405.                 if ( inBefore == mParent -> GetTail() )                    // if inserting after the last ob in the group...
  406.                      mParent -> mTail = this;                            // tell group that this is the new end ob in the group
  407.                     
  408.                 mPrev = inBefore;                                        // set this ob's prev ob ptr to the ob we're inserting after
  409.  
  410.                 mNext = inBefore -> GetNext();                            // obtain the ob this is to be inserted before
  411.                 if ( mNext )                                             // if a next ob exists...
  412.                     mNext -> mPrev = this;                                // then tell it this is its new prev ob ptr
  413.  
  414.                 mPrev -> mNext = this;                                    // tell prev ob that this is its next ob
  415.             }
  416.         }
  417.     }
  418. }
  419.  
  420.  
  421.  
  422. void nodeClass::insertAfter( long inAfterNode, nodeClass* inNodeToAdd ) {
  423.     nodeClass* insertPt = findSubNode( inAfterNode );
  424.     
  425.     if ( inNodeToAdd ) {
  426.         if ( insertPt )
  427.             inNodeToAdd -> insertAfter( insertPt );
  428.         else if ( inAfterNode <= 0 )
  429.             addToHead( inNodeToAdd );
  430.         else
  431.             addToTail( inNodeToAdd );
  432.     }
  433. }
  434.  
  435.  
  436.  
  437.  
  438.  
  439. long nodeClass::findInstance() const {
  440.     long             nodeCount        = 0;
  441.     nodeClass*        nodePtr;
  442.     int                foundMatch         = false;
  443.     
  444.     if ( mParent ) {
  445.         nodePtr = mParent -> GetHead();
  446.         
  447.         while ( nodePtr && ! foundMatch ) {
  448.             nodeCount++;
  449.             if ( this == nodePtr ) 
  450.                 foundMatch = true;
  451.             nodePtr = nodePtr -> GetNext();
  452.         }
  453.     }
  454.     
  455.     if ( foundMatch )
  456.         return nodeCount;
  457.     else
  458.         return 0;
  459. }
  460.     
  461.  
  462.  
  463.  
  464.  
  465.  
  466. void nodeClass::absorbContents( nodeClass* inSourceList, int inPutAtHead ) {
  467.     nodeClass*    nodePtr;
  468.     
  469.     if ( inSourceList ) {
  470.         do {
  471.             if ( inPutAtHead ) {
  472.                 nodePtr = inSourceList -> mTail;
  473.                 addToHead( nodePtr ); }
  474.             else {
  475.                 nodePtr = inSourceList -> mHead;
  476.                 addToTail( nodePtr );
  477.             }
  478.         } while ( nodePtr );
  479.     }
  480.  
  481. }
  482.  
  483.  
  484.  
  485.  
  486.  
  487.  
  488. void nodeClass::absorbAfter( nodeClass* inSourceList ) {
  489.     nodeClass*    nodePtr;
  490.     nodeClass*    lastPtr = this;
  491.     
  492.     if ( inSourceList && mParent ) {
  493.         do {
  494.             nodePtr = inSourceList -> mHead;
  495.             if ( nodePtr ) {
  496.                 nodePtr -> insertAfter( lastPtr );
  497.                 lastPtr = nodePtr;
  498.             }
  499.         } while ( nodePtr );
  500.     }
  501. }
  502.  
  503.  
  504.  
  505.  
  506.  
  507.  
  508. void nodeClass::deleteContents() {
  509.     nodeClass*         nodePtr         = mHead;
  510.     nodeClass*         nextNodePtr;
  511.     
  512.     while ( nodePtr ) {
  513.         nextNodePtr = nodePtr -> GetNext();
  514.         delete nodePtr;
  515.         nodePtr = nextNodePtr;
  516.     }
  517. }
  518.  
  519.  
  520.  
  521.  
  522.  
  523.  
  524.  
  525.     
  526.     
  527.     
  528.  
  529.  
  530.  
  531.  
  532.  
  533.  
  534.  
  535.  
  536.  
  537.  
  538. void nodeClass::addToHead( nodeClass* nodeToAdd ) {
  539.     if ( nodeToAdd ) {
  540.         nodeToAdd -> detach();                                // Detach it before we add it here
  541.         nodeToAdd -> mParent = this;                        // let ob know where parent group is
  542.         UpdateCounts( 1 );
  543.         if ( mTail == NULL) {                                // if this is the 1st item in the list to be...
  544.             nodeToAdd -> mPrev = NULL;                        // there is no prev link
  545.             nodeToAdd -> mNext = NULL;                         // there is no next link
  546.             mHead = mTail = nodeToAdd;    }                    // let link header know where the 1st and last link is
  547.         else {                                                // if there is already items in the list...
  548.             mHead -> mPrev = nodeToAdd;                        // let old first link know where new last link is
  549.             nodeToAdd -> mPrev = NULL;                        // tell new last link there is no prev link 
  550.             nodeToAdd -> mNext = mHead;                     // let new first link know where old last link is
  551.             mHead = nodeToAdd;                                 // let link header know where new last link is
  552.         }
  553.     }
  554. }
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561. void nodeClass::addToTail( nodeClass* nodeToAdd ) {
  562.     if ( nodeToAdd ) {                                        // if i have a valid ptr...
  563.         nodeToAdd -> detach();                                // Detach it before we add it here
  564.         nodeToAdd -> mParent = this;                        // let ob know where parent group is
  565.         UpdateCounts( 1 );
  566.         if ( mHead ) {                                        // if there is already items in the list...
  567.             mTail -> mNext = nodeToAdd;                        // let old last link know where new last link is
  568.             nodeToAdd -> mPrev = mTail;                        // let new last link know where old last link is
  569.             nodeToAdd -> mNext = NULL;                         // tell new last link there is no next link
  570.             mTail = nodeToAdd;     }                            // let link header know where new last link is
  571.         else {                                                // if this is the 1st item in the list to be...
  572.             nodeToAdd -> mPrev = NULL;                        // there is no prev link
  573.             nodeToAdd -> mNext = NULL;                         // there is no next link
  574.             mHead = nodeToAdd;                                // let link header know where the 1st link is
  575.             mTail = nodeToAdd;                                 // let link header know where the last link is
  576.         }
  577.     }                                                            
  578. }
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.  
  589.  
  590.  
  591.  
  592. long nodeClass::CountDepth( const nodeClass* inCeiling ) const {
  593.     nodeClass*    nodePtr = mParent;
  594.     int            count = 1;
  595.     
  596.  
  597.     while ( nodePtr && nodePtr != inCeiling ) {
  598.         nodePtr = nodePtr -> GetParent();
  599.         count++;
  600.     }
  601.     
  602.     if ( ! nodePtr )
  603.         count--;
  604.  
  605.     return count;
  606. }
  607.  
  608.  
  609.  
  610.  
  611.     
  612. nodeClass* nodeClass::findNodeNum( long inNum ) {
  613.     nodeClass*        nodePtr     = mHead;
  614.     int                nodeCount    = 0;
  615.     
  616.     while ( nodePtr ) {
  617.         nodeCount++;
  618.         if ( nodeCount == inNum )
  619.             return nodePtr;
  620.         nodePtr = nodePtr -> GetNext();
  621.     }
  622.     
  623.     return NULL;
  624.  
  625. }
  626.  
  627.  
  628. /*
  629.  
  630. nodeClass* nodeClass::findPrevNonMarkedSubNode( long inNum ) {
  631.     nodeStep    i( this );
  632.     nodeClass*    start         = findSubNode( inNum );    
  633.     nodeClass*    nodePtr     = i.GetNext();
  634.     nodeClass*    prevPtr     = NULL;    
  635.     
  636.     if ( start ) {
  637.         if ( start -> isMarked() )  {
  638.             while ( nodePtr != start ) {
  639.                 if ( ! nodePtr -> isMarked() )
  640.                     prevPtr = nodePtr;
  641.                         
  642.                 nodePtr = i.GetNext();
  643.             }
  644.             start = prevPtr;
  645.         }     
  646.     }
  647.     
  648.     return start;
  649. }
  650. */
  651.  
  652.  
  653.  
  654. nodeClass* nodeClass::GetDeepTail() const {
  655.     nodeClass* retPtr = mTail;
  656.     
  657.     if ( retPtr ) {
  658.         while ( retPtr -> mTail )
  659.             retPtr = retPtr -> mTail;
  660.     }
  661.     
  662.     return retPtr;
  663. }
  664.  
  665.  
  666. /*
  667. Not Yet Tested:
  668. nodeClass* nodeClass::GetParentDeepTail( const nodeClass* inCeiling ) const {
  669.     nodeClass* retPtr = this;
  670.     int n = CountOverhang( inCeiling );
  671.     
  672.     while ( n > 0 && retPtr )
  673.         retPtr = retPtr -> GetParent();
  674. }
  675. */
  676.  
  677. int nodeClass::CountOverhang( const nodeClass* inCeiling ) const {
  678.     const nodeClass*    nodePtr    = this;
  679.     int                 n        = 0;
  680.     
  681.     while ( nodePtr && inCeiling != nodePtr ) {
  682.         if ( nodePtr -> GetNext() )
  683.             return n;
  684.         nodePtr = nodePtr -> GetParent();
  685.         n++;
  686.     }
  687.     
  688.     return n;
  689. }
  690.  
  691.  
  692. nodeClass* nodeClass::findSubNode( long inNum ) {
  693.     nodeClass*        nodePtr = mHead;
  694.     long            d, i = 0;
  695.     
  696.     if ( inNum > 0 ) {
  697.         while ( nodePtr ) {                                            // Loop while there's nodes and we haven't found desired
  698.             i++;
  699.             if ( inNum == i )                                        // If we found the desired node
  700.                 return nodePtr;
  701.             else {
  702.                 d = nodePtr -> deepCount();                            // See how big this sub tree is.
  703.                 if ( inNum - i <= d )                                // If stepping over it will miss our desired node
  704.                     return nodePtr -> findSubNode( inNum - i );        // Then the node we want is inside this sub tree
  705.                 else {                                
  706.                     i += d;                                            // We can step over this sub tree, baby.
  707.                     nodePtr = nodePtr -> GetNext();    
  708.                 }
  709.             }
  710.         }
  711.                                                                     // i contains the deep count if above loop terminated
  712.         mDeepCount = i;                                                // If deepCount is invalid, we might as well use what we have
  713.     }
  714.     
  715.     return NULL;
  716. }
  717.  
  718.  
  719.  
  720. long nodeClass::findSubNode( nodeClass* inNodePtr ) {
  721.     nodeClass*        nodePtr        = mHead;
  722.     long            d, n = 0;
  723.     bool            done = false;
  724.     
  725.     while ( nodePtr && ! done ) {                    // Loop till end of shallow list or until we found desired node
  726.         n++;                                        // Count the shallow node we're on right now
  727.         if ( nodePtr == inNodePtr )                    // Is the current (shallow) node our man?
  728.             done = true;
  729.         else {
  730.             d = nodePtr -> findSubNode( inNodePtr );
  731.             if ( d > 0 ) {                            // If desired node was in the shallow node's deep tree
  732.                 done = true;
  733.                 n += d; }                            // Adjust n to be the correct num for <inNodePtr>
  734.             else {
  735.                 n += nodePtr -> deepCount();        // Adjust n to reflect the current # of nodes checked
  736.                 nodePtr = nodePtr -> GetNext();        // Move to the next shallow node
  737.             }
  738.         }
  739.     }
  740.     
  741.     if ( ! done ) {                                    // If a match wasn't found...
  742.         if ( mDeepCount < 0 )                        // If deep count # was invalid        
  743.             mDeepCount = n;                            // We might as well use what we info we have
  744.         n = 0;
  745.     }
  746.         
  747.     return n;
  748. }
  749.  
  750.  
  751.  
  752.  
  753. long nodeClass::deepCount() {
  754.     nodeClass*    nodePtr;
  755.     
  756.     if ( mDeepCount < 0 ) {                                // If the cached counter was/is invalid
  757.         nodePtr = mHead;
  758.         mDeepCount = mShallowCount;                        // Prepare to recompute it
  759.         while ( nodePtr ) {
  760.             mDeepCount += nodePtr -> deepCount();
  761.             nodePtr = nodePtr -> GetNext();
  762.         }
  763.     }
  764.         
  765.     return mDeepCount;    
  766. }
  767.  
  768.  
  769.  
  770.  
  771. nodeClass* nodeClass::NextInChain( const nodeClass* inCeiling ) const {
  772.     nodeClass* nodePtr, *retPtr;
  773.     
  774.     if ( mHead )
  775.         return mHead;
  776.     else if ( this == inCeiling )
  777.         return NULL;
  778.     else if ( mNext )
  779.         return mNext;
  780.     else { 
  781.         nodePtr = mParent;
  782.         retPtr     = NULL;
  783.         while ( nodePtr && ! retPtr && inCeiling != nodePtr ) {
  784.             retPtr    = nodePtr -> GetNext();
  785.             nodePtr = nodePtr -> GetParent();
  786.         }
  787.         return retPtr;
  788.     }
  789. }
  790.  
  791.  
  792.  
  793.  
  794.  
  795. nodeClass* nodeClass::PrevInChain( const nodeClass* inCeiling ) const {
  796.     nodeClass* retPtr;
  797.     
  798.     if ( mPrev ) {
  799.         retPtr = mPrev;
  800.         while ( retPtr -> mTail )
  801.             retPtr = retPtr -> mTail;
  802.         return retPtr; }
  803.     else if ( mParent != inCeiling )
  804.         return mParent;
  805.     else
  806.         return NULL;
  807. }
  808.  
  809.  
  810. /*
  811. Is code-opposite of NextInChain(), but does not *do* the opposite:
  812. nodeClass* nodeClass::PrevInChain( const nodeClass* inCeiling ) const {
  813.     nodeClass* nodePtr, *retPtr;
  814.     
  815.     if ( mTail )
  816.         return mTail;
  817.     else if ( mPrev )
  818.         return mPrev;
  819.     else { 
  820.         nodePtr = mParent;
  821.         retPtr     = NULL;
  822.         while ( nodePtr && ! retPtr && inCeiling != nodePtr ) {
  823.             retPtr    = nodePtr -> GetPrev();
  824.             nodePtr = nodePtr -> GetParent();
  825.         }
  826.         return retPtr;
  827.     }
  828.  
  829. }
  830. */
  831.  
  832.  
  833.  
  834.  
  835.  
  836.  
  837.  
  838.  
  839.  
  840.  
  841. void nodeClass::StartRead( CEgIStream* inStream ) {
  842.  
  843.     if ( inStream ) {
  844.         if ( inStream -> noErr() ) {
  845.             inStream -> GetByte();                // Throw away type flag for head node to be read
  846.             ReadFrom( inStream );
  847.         }
  848.     }
  849. }
  850.  
  851.  
  852.  
  853.  
  854. void nodeClass::ReadFrom( CEgIStream* inStream ) {
  855.     int            kind;
  856.     nodeClass*    nodePtr;    
  857.  
  858.     do {
  859.         kind = inStream -> GetByte();
  860.         
  861.         if ( kind != cEgSubEnd ) {
  862.             nodePtr = CreateNode( kind, this );
  863.             if ( nodePtr )
  864.                 nodePtr -> ReadFrom( inStream );
  865.             else
  866.                 inStream -> throwErr( cCorrupted );
  867.         }
  868.             
  869.     } while ( inStream -> noErr() && kind != cEgSubEnd );
  870.  
  871. }
  872.  
  873.  
  874.  
  875.  
  876. void nodeClass::WriteTo( CEgOStream* inStream ) {
  877.     nodeClass*     nodePtr = mHead;
  878.         
  879.     inStream -> PutByte( mType );
  880.     
  881.     while ( nodePtr && inStream -> noErr() ) {
  882.         nodePtr -> WriteTo( inStream );
  883.         nodePtr = nodePtr -> GetNext();
  884.     }
  885.     inStream -> PutByte( cEgSubEnd );
  886. }
  887.  
  888.  
  889.  
  890.  
  891.  
  892. void nodeClass::RandomizeSubs() {
  893.     long        rnd, i;
  894.     nodeClass*    nodePtr;
  895.     nodeClass    holder;
  896.         
  897.     for ( i = shallowCount(); i > 0; i-- ) {
  898.         rnd = Rnd( 1, i );
  899.         nodePtr = findNodeNum( rnd );
  900.         holder.addToTail( nodePtr );
  901.     }
  902.     
  903.     absorbContents( &holder );
  904. }
  905.  
  906.  
  907.  
  908.  
  909.  
  910.  
  911.  
  912. long nodeClass::Rnd( long min, long max ) {
  913.     long maxRnd     = RAND_MAX;
  914.     long retNum     = rand() * ( max - min + 1 ) / maxRnd + min;
  915.     
  916.     if ( retNum >= max )
  917.         return max;
  918.     else
  919.         return retNum;
  920. }
  921.  
  922.  
  923.  
  924.  
  925.  
  926.  
  927.  
  928.  
  929.  
  930.  
  931.  
  932.  
  933.  
  934.